package cn.anc.aonicardv.widget;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.File;

import androidx.annotation.NonNull;
import cn.anc.aonicardv.Constant;
import cn.anc.aonicardv.MyApplication;
import cn.anc.aonicardv.R;
import cn.anc.aonicardv.event.UpdateWifiName;
import cn.anc.aonicardv.module.ui.MainActivity;
import cn.anc.aonicardv.net.ApiManager;
import cn.anc.aonicardv.net.NetRequestClient;
import cn.anc.aonicardv.net.download.DownLoadCallBack;
import cn.anc.aonicardv.net.download.DownLoadManager;
import cn.anc.aonicardv.net.upload.CustomFileUpload;
import cn.anc.aonicardv.net.upload.UploadSubscriber;
import cn.anc.aonicardv.param.ParamManager;
import cn.anc.aonicardv.util.DialogUtils;
import cn.anc.aonicardv.util.EncrytUtils;
import cn.anc.aonicardv.util.NetUtils;
import cn.anc.aonicardv.util.WifiAutoConnectManager;
import cn.anc.aonicardv.util.ui.IpUtil;
import cn.anc.httpcontrolutil.CarControl;
import cn.anc.httpcontrolutil.CarControlCommand;
import cn.anc.httpcontrolutil.HttpFirmwareUpload;
import cn.anc.httpcontrolutil.SocketUtils;
import retrofit2.converter.scalars.ScalarsConverterFactory;
import rx.Subscription;

/**
 * Created by yangdai on 2017/12/1.
 */

public class FirmwareUpdateDialog extends Dialog implements CarControl.OnNotificationHandler, CarControl.OnHeartBeatCallBack {

    private TextView updateStatusTv;
    private TextView updateContentTv;
    private TextView updateRocketTv;
    private TextView versionCodeTv;
    private TextView progressTv;
    private TextView updateTv;
    private TextView cancelTv;
    private FirmwareDownloadCallback firmwareDownloadCallback;
    private String model;
    private String firmwareName;
    private Subscription subscription;
    private CircleProgressView circleProgressView;
    private NetRequestClient netRequestClient;
    private ApiManager apiManager;
    private String path;
    private Context context;
    private String serverMd5;
    private int id;
    private WifiManager wifiManager;
    private CustomFileUpload customFileUploadThread;
    private DialogUtils dialogUtils;

    private String TAG = FirmwareUpdateDialog.class.getSimpleName();
    private boolean isSendNotification = false;
    private final int HANDLER_DEFULT_TIME_OUT = 100;
    private final int HANDLER_DEFULT_UPDATE_FAILED = 200;


    public FirmwareUpdateDialog(@NonNull Context context, int themeResId, String model, String firmwareName, String md5, int mId) {
        super(context, themeResId);
        Log.e("llcFirmwareUpdateDialog","--------init-----serverMd5---:"+md5);
        this.context = context;
        this.model = model;
        this.firmwareName = firmwareName;
        this.serverMd5 = md5;
        this.id = mId;
        init();
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case HANDLER_DEFULT_TIME_OUT:
                    int cacheId =  msg.arg1;
                    if (cacheId==id&&isShowing()){
                        Toast.makeText(context, context.getString(R.string.time_out), Toast.LENGTH_SHORT).show();
                        dismiss();
                    }

                    break;
                case HANDLER_DEFULT_UPDATE_FAILED:
                    int cacheFailedId =  msg.arg1;
                    if (cacheFailedId==id&&isShowing()){
                        Toast.makeText(context, context.getString(R.string.update_failed), Toast.LENGTH_LONG).show();
                        dismiss();
                    }
                    break;

            }
        }
    };

    private void init() {
        wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        NetRequestClient.Builder builder = new NetRequestClient.Builder();
        netRequestClient = builder.addConverterFactory(ScalarsConverterFactory.create()).baseUrl(ParamManager.CarServerParam.http_base_url).build();
        apiManager = netRequestClient.getRetrofit().create(ApiManager.class);
        isSendNotification = false;
        setContentView(R.layout.dialog_firmware_update);
        setCanceledOnTouchOutside(false);
        setCancelable(true);
        updateStatusTv = findViewById(R.id.tv_update_status);
        updateContentTv = findViewById(R.id.tv_update_content);
        updateRocketTv = findViewById(R.id.tv_update_rocket);
        versionCodeTv = findViewById(R.id.tv_version_code);
        circleProgressView = findViewById(R.id.circleProgressView);
        progressTv = findViewById(R.id.tv_progress);
        updateTv = findViewById(R.id.tv_update);
        cancelTv = findViewById(R.id.tv_cancel);
        dialogUtils = new DialogUtils();
        CarControl.setGuiNotificationHandler(FirmwareUpdateDialog.this);
        updateTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (updateTv.getText().toString().equals(v.getContext().getString(R.string.update))) {
                    setCancelable(false);
                    updateRocketTv.setVisibility(View.GONE);
                    updateTv.setText(R.string.update_cancel);
                    updateStatusTv.setText(R.string.downloading_firmware);
                    progressTv.setText("0%");
                    firmwareDownloadCallback = new FirmwareDownloadCallback();

                    subscription = DownLoadManager.getInstance().download(Constant.NetParam.BASE_URL + "static/default/ota/" + model + "/" + firmwareName, DownLoadManager.DOWNLOAD_PATH_ROOT + "/" + firmwareName, firmwareDownloadCallback);
                } else {
                    updateCancelAlert();
                }
            }
        });
        cancelTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                updateCancelAlert();
            }
        });
        setOnDismissListener(new OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                isSendNotification = false;
                if (customFileUploadThread != null) {
                    customFileUploadThread.stopThread(true);
                    customFileUploadThread = null;
                }
                if (subscription != null) {
                    subscription.unsubscribe();
                }
                upLoadSubscriber.unsubscribe();
                firmwareDownloadCallback = null;

                subscription = null;
                upLoadSubscriber = null;
                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
                    DownLoadManager.getInstance().setNetwork(SocketUtils.wifiNetwork).settingOk();
                } else
                    EventBus.getDefault().unregister(FirmwareUpdateDialog.this);
            }
        });
    }

    private void updateCancelAlert() {
        dialogUtils.getAlertDialog(context).setMessage(R.string.update_cancel_alert).setNegativeButton(R.string.cancel, new OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        }).setPositiveButton(R.string.ok, new OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dismiss();
            }
        }).show();
    }

    public void setUpdateContent(String updateContent) {
        updateContentTv.setText(updateContent);
    }

    public void setVersionCode(String versionCode) {
        versionCodeTv.setText(versionCode);
    }

    @Override
    public void OnHeartBeatConnectOK() {
        Log.e("llcFirmwareUpdateDialog","-------------CarControl.DeviceInfo.chip---:"+CarControl.DeviceInfo.chip);
        if (null!=CarControl.DeviceInfo.chip&&CarControl.DeviceInfo.chip.equals("MSTAR")) {
            VerifyMd5();
        } else {
            uploadFirmware();
        }

    }


    private void VerifyMd5() {
        Log.e("llcFirmwareUpdateDialog","--------VerifyMd5-----serverMd5---:"+serverMd5);
        CarControl.doVerifyMd5(serverMd5, carControlCallback);
    }

    HttpFirmwareUpload.HttpFileUploadListener mHttpFileUploadListener = new HttpFirmwareUpload.HttpFileUploadListener() {
        @Override
        public void onStart() {
        }

        @Override
        public void onError(String error) {
            Toast.makeText(context, context.getString(R.string.update_failed), Toast.LENGTH_LONG).show();
            dismiss();
        }

        @Override
        public void onUploadProgress(float progress) {
            progressTv.setText((int) (100 * progress) + "%");
            circleProgressView.setProgress((int) (360.0 * progress));
        }

        @Override
        public void onSuccess() {
            cancelTv.setEnabled(false);
            updateTv.setEnabled(false);
            updateTv.setTextColor(context.getResources().getColor(R.color.btn_com_disable_background));
            CarControl.setGuiNotificationHandler(FirmwareUpdateDialog.this);
            isSendNotification = true;
            final Message successMsg = new Message();
            successMsg.what = HANDLER_DEFULT_TIME_OUT;
            successMsg.arg1 = id;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(100000);
                        mHandler.sendMessage(successMsg);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

        }
    };

    private CarControlCallback carControlCallback = new CarControlCallback();


    class CarControlCallback implements CarControl.OnCarControlCallback {
        @Override
        public void OnCommandCallback(int code, CarControl.CommandResponseInfo info) {
            Log.e("llcFirmwareUpdateDialog","--------info--------:"+info.toString());
            if (code < 0)
                return;
            switch (info.msg_id) {
                case CarControlCommand.CAR_CONTROL_COMMAND_ID_SEND_FIREWARE_MD5:
                    if (info.rval == 0) {
                        uploadMstarFirmware();
                    } else {
                        Toast.makeText(context, context.getString(R.string.fw_firmware_md5_failed), Toast.LENGTH_LONG).show();
                        dismiss();
                    }
                    break;
                default:
                    Toast.makeText(context, context.getString(R.string.fw_firmware_md5_failed), Toast.LENGTH_LONG).show();
                    dismiss();
                    break;
            }
        }
    }


    private void uploadMstarFirmware() {
        //处理路径成ip  端口
        String otaUrl = CarControl.DeviceInfo.ota_path;
        if (TextUtils.isEmpty(otaUrl)) {
            otaUrl = "http://" + MyApplication.IP + ":" + ParamManager.CarServerParam.CarControlHttpPort + "/?custom=1&file_upload&md5=";
        }
        HttpFirmwareUpload HttpFirmwareUpload = new HttpFirmwareUpload((Activity) context, otaUrl, "upload_key", path, mHttpFileUploadListener);
        HttpFirmwareUpload.start();
    }


    private void uploadFirmware() {
        File file = new File(path);
        //处理路径成ip  端口
        String otaUrl = CarControl.DeviceInfo.ota_path;
        String _ip = IpUtil.getOtaIp(otaUrl);
        int _port = IpUtil.getOtaPort(otaUrl);
        String _upload_uri = IpUtil.getOtaUploadUri(otaUrl);
        if (null != _ip && null != _upload_uri) {
            customFileUploadThread = new CustomFileUpload(_ip,
                    _port,
                    _upload_uri,
                    file);
        } else {
            customFileUploadThread = new CustomFileUpload(MyApplication.IP,
                    ParamManager.CarServerParam.CarControlHttpPort,
                    "/?custom=1&file_upload&md5=",
                    file);
        }

        customFileUploadThread.setUploadCallback(upLoadSubscriber);
        customFileUploadThread.start();
    }

    @Override
    public void OnHeartBeatConnectFail() {
    }

    @Override
    public void OnHeartBeatDisconnect() {
    }

    @Override
    public void OnNotication(CarControl.NotificationInfo info) {
        if (info.param.equals("ok")) {
            Toast.makeText(context, context.getString(R.string.update_success), Toast.LENGTH_SHORT).show();
            CarControl.HeartBeatStop();
            context.startActivity(new Intent(context, MainActivity.class));
            dismiss();
        } else {
            if (isSendNotification) {
                Toast.makeText(context, context.getString(R.string.update_failed), Toast.LENGTH_SHORT).show();
                dismiss();
            }

        }

    }


    public class FirmwareDownloadCallback extends DownLoadCallBack {

        @Override
        public void onStart() {
            super.onStart();
        }

        @Override
        public void onError(String e) {
            Toast.makeText(context, context.getString(R.string.my_download_failed), Toast.LENGTH_SHORT).show();
            dismiss();
        }

        @Override
        public void onProgress(long fileSizeDownloaded, long totalSize) {
            float f = (float) fileSizeDownloaded / totalSize;
            progressTv.setText((int) (100 * f) + "%");
            circleProgressView.setProgress((int) (360.0 * f));
        }

        @Override
        public void onCompleted(String path, Uri uri) {
            FirmwareUpdateDialog.this.path = path;
            if (EncrytUtils.getMd5ByFile(new File(path)).equalsIgnoreCase((serverMd5))) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    ConnectivityManager.setProcessDefaultNetwork(SocketUtils.wifiNetwork);
                    if (null != CarControl.DeviceInfo.chip && CarControl.DeviceInfo.chip.equals("MSTAR")) {
                        VerifyMd5();
                    } else {
                        uploadFirmware();
                    }

                } else {
                    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
                        CarControl.setOnHeartBeatCallBack(FirmwareUpdateDialog.this);
                        EventBus.getDefault().register(FirmwareUpdateDialog.this);
                    }
                    if (!TextUtils.isEmpty(MyApplication.wifiSSID) && !TextUtils.isEmpty(MyApplication.wifiPassword)) {
                        WifiAutoConnectManager w = new WifiAutoConnectManager(wifiManager);
                        w.connect(MyApplication.wifiSSID, MyApplication.wifiPassword, WifiAutoConnectManager.WifiCipherType.WIFICIPHER_WPA);
                    }
                }
                progressTv.setText("0%");
                updateStatusTv.setText(R.string.updating_firmware);
            } else {
                Toast.makeText(context, context.getString(R.string.fw_firmware_md5_failed), Toast.LENGTH_LONG).show();
                dismiss();
            }
        }
    }


    UploadSubscriber upLoadSubscriber = new UploadSubscriber() {
        @Override
        public void onError(Throwable e) {

            final Message errMsg = new Message();
            errMsg.what = HANDLER_DEFULT_UPDATE_FAILED;
            errMsg.arg1 = id;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(500);
                        mHandler.sendMessage(errMsg);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();




        }

        @Override
        public void onNext(String o) {
        }

        @Override
        public void onProgress(long fileSizeDownloaded, long totalSize) {
            float f = (float) fileSizeDownloaded / totalSize;
            progressTv.setText((int) (100 * f) + "%");
            circleProgressView.setProgress((int) (360.0 * f));

        }

        @Override
        public void onSuccess() {
            cancelTv.setEnabled(false);
            updateTv.setEnabled(false);
            updateStatusTv.setText(R.string.upload_firmware_success);
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    progressTv.setText(" ");
                    circleProgressView.setAutoProgress();
                    updateStatusTv.setText(R.string.checking_firmware);
                }
            }, 1000);
            updateTv.setTextColor(context.getResources().getColor(R.color.btn_com_disable_background));
            CarControl.setGuiNotificationHandler(FirmwareUpdateDialog.this);
            isSendNotification = true;
            final Message msg = new Message();
            msg.what = HANDLER_DEFULT_TIME_OUT;
            msg.arg1 = id;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(30000);
                        mHandler.sendMessage(msg);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

        }
    };

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(UpdateWifiName event) {
        String ip = NetUtils.getWifiIpAddress(context);
        if (MyApplication.IPHeader != null && ip != null && ip.contains(MyApplication.IPHeader) && MyApplication.wifiSSID != null
                && !CarControl.IsConnected.get()
                ) {
            CarControl.HeartBeatStart(MyApplication.IP, ParamManager.CarServerParam.CarControlNotifyPort,"hi","car");
        }
    }
}
